#!/usr/bin/env python
# coding:utf-8
"""Modelo de datos para el alacenamiento y busqueda de base de datos  """


import functools
from panacea import metadata
from panacea import session
from panacea import Entity
from panacea import Field
from panacea import UnicodeText
from panacea import ManyToMany
from panacea import Enum
from panacea import BOOLEAN
from panacea import PickleType


class Rule(Entity):
    pattern = Field(UnicodeText)
    validators = ManyToMany('Validator')
    default = Field(Enum('replace', 'ignore', 'append', 'prepend'))

    def __repr__(self):
        return 'Rule: %s for %s' % (self.pattern, self.apply_to)


class Validator(Entity):
    name = Field(UnicodeText, primary_key=True)
    builtin = Field(UnicodeText)
    params = Field(PickleType, default={})
    simple = Field(BOOLEAN, default=True)
    childs = ManyToMany('Validator')
    rules = ManyToMany('Rule')
    doc = Field(UnicodeText)

    def __repr__(self):
        return 'Validator:%s' % self.name


def find(rule, params={}):
    '''find(rule:str, params:dict)'''
    if rule in BUILTINS:
        r = BUILTINS[rule](params)
        return r
    else:
        r = Validator.get_by(name=rule)
        try:
            call = BUILTINS[r.name](r.params)
            return call
        except TypeError:
            return None


def search(pattern):
    r = Rule.get_by(pattern=pattern)
    s = []
    try:
        for v in r.validators:
            s.append(v.name)
    except AttributeError:
        pass
    return s


BUILTINS = {}


def rule(use_as, alias=''):
    '''rule(function:callable, alias:str)-> decorator'''
    def inner(func):
        def valide(kwargs):
            f = functools.partial(func, **kwargs)
            f.use_as = use_as
            return f
        BUILTINS[alias if alias else func.__name__ ] = valide
        return valide
    return inner


@rule('setup')
def readOnly(widget):
    widget.read_only = True


@rule('setup')
def default(widget, value):
    widget.value = value


@rule('valide')
def rut(value):
    pass


@rule('valide')
def natural(value):
    pass


@rule('valide')
def date(value):
    pass


@rule('valide')
def limit(value, maximum=None, minimum=None):
    pass


@rule('valide')
def maxLength(value, length):
    return len(value) <= self.length


@rule('valide')
def notEmpty(value):
    return bool(value)


